package main

import (
	"errors"
	"github.com/go-redis/redis"
	uuid "github.com/satori/go.uuid"
	"sync"
	"time"
)

//    RedisSessionMgr设计：
//    定义RedisSessionMgr对象（字段：存放所有session的map，读写锁）
//    构造函数
//    Init()
//    CreateSeesion()
//    GetSession()

type RedisSessionMgr struct {
	// redis地址
	addr string
	// 密码
	passwd string
	//连接池
	pool *redis.Pool
	// 锁
	rwlock sync.RWMutex
	// 大map
	sessionMap map[string]Session
}



// 构造函数
func NewRedisSessionMgr() SessionMgr{
	sr := &RedisSessionMgr{
		sessionMap: make(map[string]Session, 32),
	}
	return sr
}

func (r *RedisSessionMgr) Init(addr string, options ...string) (err error) {
	// 若其他参数
	if len(options) >0 {
		r.passwd = options[0]
	}
	// 创建连接池
	r.pool = myPool(addr, r.passwd)
	r.addr = addr
	return
}

func myPool(addr string, password string) *redis.Pool{
	return &redis.Pool{
		MaxIdle: 64,
		MaxActive: 1000,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error){
			conn, err := redis.Dial("tcp", addr)
			if err != nil{
				return nil,err
			}
			// 若有密码，判断
			if _,err := conn.Do("AUTH", password); err != nil{
				conn.Close()
				return nil,err
			}
			return conn, err
		},
		// 连接测试,开发时写, 上线注释掉

		TestOnBorrow: func(conn redis.Conn, t time.Time) error{
			_, err := conn.Do()
		},
	}
}

func (r *RedisSessionMgr) CreateSession() (session Session, err error) {
	r.rwlock.Lock()
	defer r.rwlock.Unlock()
	// go get github.com/satori/go.uuid
	// 用uuid作为sessionId
	id, err := uuid.NewV4()
	if err != nil{
		return
	}
	// 转string
	sessionId := id.String()
	// 创建单个session
	session = NewRedisSession(sessionId, r.pool)
	// 加入到大map
	r.sessionMap[sessionId] = session

	return
}

func (r *RedisSessionMgr) Get(sessionId string) (session Session, err error) {
	r.rwlock.Lock()
	defer r.rwlock.Unlock()
	session, ok := r.sessionMap[sessionId]
	if !ok{
		err = errors.New("session not exist")
		return
	}
	return
}